package Readers;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import NWPackage.Calculations;
import NWPackage.OneSettingDistMatrix;
import NWPackage.ProbabilityCell;
import NWPackage.RealVoteCell;
import Writers.MsgLog;

public class ExperimentSkewnessExcelInputs extends Inputs {

	private final String THIS_FOLDER = System.getProperty("user.dir")+"\\Experiments\\";
	private int huristic;
	private int MC_LOOPS = 1000; //default
	private HSSFWorkbook w;
	private File inputWorkbook;
	private String inputFile;
	private int numVotes;
	private String dataType;
	private List<String> agents = new ArrayList<String>();
	private SkewnessInput skewnessReader;
	private ProbabilityCell[] allprobabilities = null;
	private RealVoteCell[] realVoteInputMatrix;
	private int numAgents;
	boolean skew_flag;
	//protected final int numAgents = agents.length;
	
	public ExperimentSkewnessExcelInputs(String inputFile, int heuristic, int iterations, SkewnessInput skewnessReader, boolean flag) throws Exception{
		this.skewnessReader = skewnessReader;
		this.huristic = heuristic;
		this.MC_LOOPS = iterations;
		this.inputFile = inputFile;
		inputWorkbook = new File(THIS_FOLDER+"\\"+inputFile);
		skew_flag = flag;
		
		try {
			read();
		} catch (Exception e) {
			MsgLog.write_to_init("Error in reading the Excel File");
			e.printStackTrace();
		}					
		
	}

	private void read() throws Exception {
		try{
			w = new HSSFWorkbook(new FileInputStream(inputWorkbook));
			//get the first sheet
			HSSFSheet sheet = w.getSheetAt(0);
			//get the Inputs:
			numAgents = (int)sheet.getRow(0).getCell(1).getNumericCellValue();
			numVotes = (int)sheet.getRow(2).getCell(1).getNumericCellValue();
			numCandidates  = (int)sheet.getRow(1).getCell(1).getNumericCellValue();			
			//check if this is a simulated data
			//isSimulated = sheet.getRow(3).getCell(1).getRichStringCellValue().getString().equals("S") ? true:false ;
			dataType = sheet.getRow(3).getCell(1).getRichStringCellValue().getString();
			if (dataType.toLowerCase().equals("ns")){
				//read new simulated (september 2012)
				if (skew_flag)
				   readInputMatrix_NS();
			}			
			else
			{
				//trow exception - read methode unknow
				//throw new Exception("please specify one of the reading methods: 'N'-Netflix, 'S'-Simulated, 'Sushi'-probs for each permutation" );
				throw new Exception("please specify one of the reading methods: 'NS' - new simulated with skewness file" );
			}
			//read the real votes matrix from Excel
			readRealVotesMatrix();						
		}
		catch (Exception e)
		{
			MsgLog.write_to_init(e.getMessage());
			System.out.println(e.getMessage());
			throw e;
			
		}
		if (!skew_flag){
			for(int j=1; j<(numAgents+1); j++){
				String agentName = Integer.toString(j);
				agents.add(agentName);
			}
		}
		
		if (skew_flag)
		    dynamicCandidates = (List<String>) skewnessReader.getCandidatesList();
		else{
			dynamicCandidates = new ArrayList<String>();
			for(int i=1; i<(numCandidates+1);i++){				
				String s =Integer.toString(i);				
			   dynamicCandidates.add(s);
			}
		}
		//numCandidates = dynamicCandidates.size();  //LIHI's change		
		
	}

	private void readRealVotesMatrix()throws Exception {
		MsgLog.write_to_init("Reading Real Vote Matrix from file");
		realVoteInputMatrix = new RealVoteCell[numAgents];
		int index = 0;
		HSSFSheet sheet = w.getSheetAt(2);
		for (int agent_cand_index = 1; agent_cand_index <= numAgents; agent_cand_index++) {
			String agentName = String.valueOf(sheet.getRow(agent_cand_index).getCell(0).getNumericCellValue());
			//loop over all votes
			List<String> candidates = new ArrayList<String>();
			for (int vote_index = 1; vote_index < sheet.getRow(agent_cand_index).getPhysicalNumberOfCells(); vote_index++) {
				candidates.add(String.valueOf((int)(sheet.getRow(agent_cand_index).getCell(vote_index).getNumericCellValue())));
			}
			realVoteInputMatrix[index] = new RealVoteCell(agentName, index, candidates);
			index++;
		}
	}

	private void readInputMatrix_NS() throws Exception {
		
		MsgLog.write_to_init("Reading the probs directly from Excel  - simulated cells");
		int permutationsCells = Calculations.calcCandidatesPermutationsNPR(numCandidates);
		allprobabilities = new ProbabilityCell[numAgents*permutationsCells];
		int index = 0;
		HSSFSheet sheet = w.getSheetAt(1);
		//loop over all the agents/candidates
		
		List<ProbabilityCell> agentProbs = null;
		
		for (int agent_index = 1; agent_index < sheet.getPhysicalNumberOfRows(); agent_index++) {
			String agentName = String.valueOf(sheet.getRow(agent_index).getCell(0).getNumericCellValue());
			agents.add(agentName);
			
			int key = (int) sheet.getRow(agent_index).getCell(1).getNumericCellValue();

			agentProbs = skewnessReader.buildSkewnessListForAgent(agentName, key);
			for (ProbabilityCell probCell : agentProbs) {
				probCell.setIndex(index);
				allprobabilities[index] = probCell;
				index++;
			}
			
		}
			
	}

	@Override
	public RealVoteCell[] realVotesMatrix() {
		return realVoteInputMatrix;
	}
	
	public ProbabilityCell[] getMatrixProbabilities()
	{
		return Clone();
	}

	private ProbabilityCell[] Clone() {
		ProbabilityCell[] clone = new ProbabilityCell[allprobabilities.length];
		for (int i = 0; i < allprobabilities.length; i++) {
			clone[i] = allprobabilities[i].clone();
		}
		return clone;
	}

	@Override
	public String[] getCandidates() {
		String[] strArray = new String[dynamicCandidates.size()];
		dynamicCandidates.toArray(strArray);
		return strArray;
	}

	@Override
	public List<String> getDynamicCandidates() {
		return dynamicCandidates;
	}

	@Override
	public int getNumCandidates() {
		return this.numCandidates;
	}

	@Override
	public String[] getAgents() {
		String[] array = new String[this.agents.size()];
		this.agents.toArray(array);
		return array;
	}

	@Override
	public int getNumAgents() {
		return this.numAgents;
	}

	@Override
	public int getMonteCarloRandomProcess() {
		return this.MC_LOOPS;
	}

	@Override
	public int getBordaMaxValue() {
		return this.numCandidates;
	}

	@Override
	public int getBordaMinValue() {
		return BORDA_MIN_VALUE;
	}
	@Override
	public String getFileName()
	{
		return this.inputFile;
	}
	@Override
	public int getHuristic()
	{
		return this.huristic;
	}


}
